"""Config flow for Device Bridge integration."""
import logging
from typing import Any, Dict, Optional
import re

import voluptuous as vol
from homeassistant import config_entries
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)

# 简化配置表单，只显示必填的 IP 地址
STEP_USER_DATA_SCHEMA = vol.Schema({
    vol.Required("ip"): str,
})


def validate_ip_completeness(value: str) -> tuple[bool, str]:
    """验证 IP 地址的完整性，返回 (是否有效, 错误信息)"""
    if not value or not value.strip():
        return False, "IP地址不能为空"
    
    value = value.strip()
    
    # 检查是否包含端口号
    if ':' in value:
        # 分离IP和端口
        if value.count(':') == 1:
            ip_part, port_part = value.split(':')
            try:
                port = int(port_part)
                if port < 1 or port > 65535:
                    return False, f"端口号 {port} 超出有效范围 (1-65535)"
                value = ip_part  # 继续验证IP部分
            except ValueError:
                return False, f"端口号 '{port_part}' 不是有效数字"
        else:
            # 可能是IPv6地址，暂时不支持
            return False, "暂不支持IPv6地址格式"
    
    # IP 地址格式验证
    ip_pattern = r'^(\d{1,3}\.){3}\d{1,3}$'
    if re.match(ip_pattern, value):
        parts = value.split('.')
        
        # 检查每个部分是否在 0-255 范围内
        try:
            for i, part in enumerate(parts):
                num = int(part)
                if num < 0 or num > 255:
                    return False, f"IP地址第{i+1}段 '{part}' 超出范围 (0-255)"
                # 检查是否有前导零（除了单独的0）
                if len(part) > 1 and part[0] == '0':
                    return False, f"IP地址第{i+1}段 '{part}' 不能有前导零"
        except ValueError:
            return False, "IP地址包含非数字字符"
        
        # 检查网络类别和特殊地址
        first_octet = int(parts[0])
        second_octet = int(parts[1])
        
        # 无效的特殊地址
        if value == "0.0.0.0":
            return False, "0.0.0.0 不是有效的主机IP地址"
        
        if value == "255.255.255.255":
            return False, "255.255.255.255 是广播地址，不能作为主机IP"
        
        # 回环地址
        if first_octet == 127:
            return False, "127.x.x.x 是回环地址，请使用实际的网络IP地址"
        
        # 链路本地地址
        if first_octet == 169 and second_octet == 254:
            return False, "169.254.x.x 是链路本地地址，请使用实际的网络IP地址"
        
        # 组播地址
        if first_octet >= 224 and first_octet <= 239:
            return False, f"{value} 是组播地址，不能作为主机IP地址"
        
        # E类地址（实验性）
        if first_octet >= 240:
            return False, f"{value} 是实验性地址，不能作为主机IP地址"
        
        # 检查是否为私有网络地址（给出提示但不阻止）
        is_private = False
        if first_octet == 10:  # 10.0.0.0/8
            is_private = True
        elif first_octet == 172 and 16 <= second_octet <= 31:  # 172.16.0.0/12
            is_private = True
        elif first_octet == 192 and second_octet == 168:  # 192.168.0.0/16
            is_private = True
        
        # 私有地址是有效的，只是给出信息提示
        if is_private:
            _LOGGER.info(f"检测到私有网络地址: {value}")
        
        return True, ""
    
    # 域名格式验证
    if len(value) > 253:
        return False, "域名长度不能超过253字符"
    
    if value.startswith('.') or value.endswith('.'):
        return False, "域名不能以点开头或结尾"
    
    if '..' in value:
        return False, "域名不能包含连续的点"
    
    # 检查是否包含非法字符
    if not re.match(r'^[a-zA-Z0-9.-]+$', value):
        return False, "域名只能包含字母、数字、点和连字符"
    
    # 域名各部分验证
    parts = value.split('.')
    
    # 至少要有一个点（除非是localhost等特殊情况）
    if len(parts) < 2 and value.lower() not in ['localhost']:
        return False, "域名格式不正确，应包含至少一个点（如：192.168.x.xx）"
    
    for i, part in enumerate(parts):
        if not part:
            return False, f"域名第{i+1}部分为空"
        if len(part) > 63:
            return False, f"域名第{i+1}部分 '{part}' 长度不能超过63字符"
        
        # 每个部分不能以连字符开头或结尾
        if part.startswith('-') or part.endswith('-'):
            return False, f"域名第{i+1}部分 '{part}' 不能以连字符开头或结尾"
        
        # 检查字符合法性
        if not re.match(r'^[a-zA-Z0-9-]+$', part):
            return False, f"域名第{i+1}部分 '{part}' 包含非法字符"
        
        # 第一个字符和最后一个字符不能是连字符
        if len(part) > 1 and (part[0] == '-' or part[-1] == '-'):
            return False, f"域名第{i+1}部分 '{part}' 格式错误"
    
    # 顶级域名检查（最后一部分应该是字母）
    if len(parts) >= 2:
        tld = parts[-1]
        if not re.match(r'^[a-zA-Z]+$', tld):
            return False, f"顶级域名 '{tld}' 应该只包含字母"
        if len(tld) < 2:
            return False, f"顶级域名 '{tld}' 长度至少为2个字符"
    
    return True, ""


class DeviceBridgeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
    """Handle a config flow for Device Bridge."""

    VERSION = 1

    async def async_step_user(
        self, user_input: Optional[Dict[str, Any]] = None
    ) -> FlowResult:
        """Handle the initial step."""
        errors = {}

        if user_input is not None:
            # 验证 IP 地址或域名（必填）
            ip = user_input.get("ip", "").strip()
            if not ip:
                errors["ip"] = "IP地址不能为空"
            else:
                # 使用严格的验证
                is_valid, error_msg = validate_ip_completeness(ip)
                if not is_valid:
                    errors["ip"] = error_msg
                else:
                    # 检查是否已经配置
                    await self.async_set_unique_id(DOMAIN)
                    self._abort_if_unique_id_configured()

                    # 设置配置数据
                    config_data = {
                        "ip": ip,
                        "enable_cors": True,  # 默认启用
                        "auto_generate_qr": True,  # 默认启用
                    }

                    return self.async_create_entry(
                        title="Device Bridge",
                        data=config_data,
                    )

        return self.async_show_form(
            step_id="user",
            data_schema=STEP_USER_DATA_SCHEMA,
            errors=errors,
            description_placeholders={
                "description": "请输入你的 Home Assistant IP 地址或域名（如：192.168.1.100 或 ha.example.com）"
            }
        )